package com.bestcem.xm.txtanls.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.bestcem.xm.common.core.domain.web.ServiceResult;
import com.bestcem.xm.txtanls.dao.AnalysisProjectDao;
import com.bestcem.xm.txtanls.dao.HiddenKeywordDao;
import com.bestcem.xm.txtanls.dao.RecordDao;
import com.bestcem.xm.txtanls.dao.TopicDao;
import com.bestcem.xm.txtanls.entity.pojo.HiddenKeywordDO;
import com.bestcem.xm.txtanls.entity.pojo.TopicDO;
import com.bestcem.xm.txtanls.entity.pojo.TopicGroupInfoDO;
import com.bestcem.xm.txtanls.enums.TopicStatusEnum;
import com.bestcem.xm.txtanls.enums.TopicTypeEnum;
import com.bestcem.xm.txtanls.grpc.service.param.topic.*;
import com.bestcem.xm.txtanls.service.TopicService;
import com.bestcem.xm.txtanls.service.dto.RecordSearchDTO;
import com.bestcem.xm.txtanls.service.dto.topic.TopicDTO;
import com.bestcem.xm.txtanls.service.dto.topic.TopicDataDTO;
import com.bestcem.xm.txtanls.service.dto.topic.TopicGroupDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.bestcem.xm.common.core.constant.Constants.*;
import static com.bestcem.xm.txtanls.util.ViewpointUtil.FREE_KEYWORD_DICT;
import static com.bestcem.xm.txtanls.util.ViewpointUtil.FREE_TOPIC_DICT;

/**
 * 话题service实现类
 *
 * @author liheng
 * @version v1.0
 * @date 2021/5/10-17:24
 */
@Service
@Slf4j
public class TopicServiceImpl implements TopicService {


    @Resource
    private TopicDao topicDao;

    @Resource
    private HiddenKeywordDao hiddenKeywordDao;

    @Resource
    private RecordDao recordDao;

    @Resource
    private AnalysisProjectDao analysisProjectDao;

    @Override
    public TopicDO getById(String id) {
        return topicDao.getById(id);
    }

    @Override
    public ServiceResult<List<TopicGroupDTO>> listGroupByProjectId(ListTopicGroupParam param) {
        String projectId = param.getProjectId();
        String fieldId = param.getFieldId();
        if (StringUtils.isNotBlank(fieldId) && !ObjectId.isValid(fieldId)) {
            return ServiceResult.fail("fieldId错误");
        }

        // 聚合查询所有话题组和话题
        List<TopicDO> allTopics = topicDao.listTopicByProjectId(projectId);
        List<TopicGroupDTO> topicGroupDTOS = new ArrayList<>(DEFAULT_ARRAY_SIZE);
        if (CollUtil.isEmpty(allTopics)) {
            return ServiceResult.success(topicGroupDTOS);
        }
        List<TopicGroupInfoDO> groupList = new ArrayList<>(allTopics.size());

        // 过滤话题组
        groupList = allTopics.stream().filter(o -> TopicTypeEnum.GROUP.getIndex() == o.getType())
                .map(o -> new TopicGroupInfoDO(o.getId(), o.getProjectId(), o.getName(), o.getType(), o.getStatus(), o.getSample()))
                .collect(Collectors.toList());
        List<TopicDO> topicList = allTopics.stream().filter(o -> TopicTypeEnum.TOPIC.getIndex() == o.getType()).collect(Collectors.toList());
        // 如果没有话题组，也不会有话题
        if (CollUtil.isEmpty(groupList)) {
            return ServiceResult.success(topicGroupDTOS);
        }
        // 组装话题组对象
        for (TopicGroupInfoDO topicGroupInfo : groupList) {
            topicGroupInfo.setTopicDOList(topicList.stream().filter(o -> topicGroupInfo.getId().equals(o.getTopicGID())).collect(Collectors.toList()));
        }
        boolean b = groupList.stream().map(TopicGroupInfoDO::getName).anyMatch(o -> o.equals(UN_GROUP));
        if (!b) {
            // 初始化未分组话题组
            TopicDO defaultGroup = topicDao.insertGroup(projectId, "未分组");
            TopicGroupInfoDO topicGroupInfo = new TopicGroupInfoDO();
            topicGroupInfo.setId(defaultGroup.getId());
            topicGroupInfo.setType(defaultGroup.getType());
            topicGroupInfo.setProjectId(defaultGroup.getProjectId());
            topicGroupInfo.setName(defaultGroup.getName());
            topicGroupInfo.setStatus(defaultGroup.getStatus());
            groupList.add(topicGroupInfo);
        }
        List<String> filedIds = analysisProjectDao.listTextFiledId(projectId, fieldId);
        RecordSearchDTO recordSearchDTO = new RecordSearchDTO();
        recordSearchDTO.setProjectId(projectId);
        recordSearchDTO.setFieldIds(filedIds);
        recordSearchDTO.setPeriodTime(ObjectUtils.isEmpty(param.getTimeRangeDTO()) ? null : param.getTimeRangeDTO().getPeriodTime());
//        recordSearchDTO.setKeywords(topicDO.getKeyDict());
        // 所有原话查询
        List<String> content = recordDao.listRecordContent(recordSearchDTO);
        for (TopicGroupInfoDO group : groupList) {
            int totalCount = 0;
            List<TopicDTO> topicDTOS = new ArrayList<>(DEFAULT_ARRAY_SIZE);

            for (TopicDO topicDO : group.getTopicDOList()) {
                int count = 0;
                if (CollUtil.isNotEmpty(topicDO.getKeyDict())) {
                    // 计算话题关键词匹配原话数
                    for (String record : content) {
                        for (String s : topicDO.getKeyDict()) {
                            if (record.contains(s)) {
                                count++;
                                // 一条原话只与话题匹配一次
                                break;
                            }
                        }
                    }
                    if (log.isInfoEnabled()) {
                        //log.info("[txtanls]: 话题组列表查询-查询原话匹配数量，消耗时间：{}", System.currentTimeMillis() - startTime);
                    }
                } else {
                    topicDO.setKeyDict(new ArrayList<>());
                }
                topicDTOS.add(new TopicDTO(topicDO.getId(), topicDO.getProjectId(), topicDO.getName(), topicDO.getTopicGID(), topicDO.getType(), count, topicDO.getKeyDict()));
                totalCount += count;
            }
            // 以匹配数量倒序排列
            topicDTOS.sort(Comparator.comparing(TopicDTO::getCount).reversed());
            TopicGroupDTO topicGroupDTO = new TopicGroupDTO(group.getId(), group.getName(), totalCount, topicDTOS);
            topicGroupDTOS.add(topicGroupDTO);
        }
        if (log.isInfoEnabled()) {
            //log.info("[txtanls]: 话题组列表查询-匹配原话，消耗时间：{}", System.currentTimeMillis() - startTime);
        }
        topicGroupDTOS.sort(Comparator.comparing(TopicGroupDTO::getTotal).reversed());
        if (log.isInfoEnabled()) {
            //log.info("[txtanls]: 话题组列表查询-排序所有话题组，消耗时间：{}", System.currentTimeMillis() - startTime);
        }
        return ServiceResult.success(topicGroupDTOS);
    }

    @Override
    public ServiceResult<List<TopicGroupDTO>> listGroupByProjectId2(ListTopicGroupParam param) {
        String projectId = param.getProjectId();
        String fieldId = param.getFieldId();
        if (StringUtils.isNotBlank(fieldId) && !ObjectId.isValid(fieldId)) {
            return ServiceResult.fail("fieldId错误");
        }
        // 聚合查询所有话题组和话题
        long startTime = System.currentTimeMillis();

        List<TopicGroupInfoDO> groupList = topicDao.aggregateTopic(projectId);
        if (log.isInfoEnabled()) {

            log.info("[txtanls]: 话题组列表查询-查询所有话题和话题组，消耗时间：{}", System.currentTimeMillis() - startTime);

        }
        List<TopicGroupDTO> topicGroupDTOS = new ArrayList<>(DEFAULT_ARRAY_SIZE);
        List<String> filedIds = analysisProjectDao.listTextFiledId(projectId, fieldId);
        if (log.isInfoEnabled()) {
            log.info("[txtanls]: 话题组列表查询-查询文本分析项目字段，消耗时间：{}", System.currentTimeMillis() - startTime);
        }

        for (TopicGroupInfoDO group : groupList) {
            int totalCount = 0;
            List<TopicDTO> topicDTOS = new ArrayList<>(DEFAULT_ARRAY_SIZE);
            for (TopicDO topicDO : group.getTopicDOList()) {
                int count = 0;
                if (CollUtil.isNotEmpty(topicDO.getKeyDict())) {
                    // 计算话题关键词匹配原话数
                    RecordSearchDTO recordSearchDTO = new RecordSearchDTO();
                    recordSearchDTO.setProjectId(projectId);
                    recordSearchDTO.setFieldIds(filedIds);
                    recordSearchDTO.setPeriodTime(ObjectUtils.isEmpty(param.getTimeRangeDTO()) ? null : param.getTimeRangeDTO().getPeriodTime());
                    recordSearchDTO.setKeywords(topicDO.getKeyDict());
                    count = recordDao.countRecord(recordSearchDTO).intValue();
                }
                topicDTOS.add(new TopicDTO(topicDO.getId(), topicDO.getProjectId(), topicDO.getName(), topicDO.getTopicGID(), topicDO.getType(), count, topicDO.getKeyDict()));
                totalCount += count;
            }
            // 以匹配数量倒序排列
            topicDTOS.sort(Comparator.comparing(TopicDTO::getCount).reversed());
            TopicGroupDTO topicGroupDTO = new TopicGroupDTO(group.getId(), group.getName(), totalCount, topicDTOS);
            topicGroupDTOS.add(topicGroupDTO);
        }
        if (log.isInfoEnabled()) {
            log.info("[txtanls]: 话题组列表查询-匹配原话，消耗时间：{}", System.currentTimeMillis() - startTime);
        }
        topicGroupDTOS.sort(Comparator.comparing(TopicGroupDTO::getTotal).reversed());
        if (log.isInfoEnabled()) {
            log.info("[txtanls]: 话题组列表查询-排序所有话题组，消耗时间：{}", System.currentTimeMillis() - startTime);
        }
        return ServiceResult.success(topicGroupDTOS);
    }

    @Override
    public ServiceResult<String> saveTopic(CreateTopicParam param) {
        String projectId = param.getProjectId();
        String name = param.getName();
        if (this.checkNameRepeat(projectId, name)) {
            return ServiceResult.fail("该名称已在话题或者话题组中存在");
        }
        if (TopicTypeEnum.GROUP.getIndex() == param.getType() && StringUtils.isNotBlank(param.getTopicGId())) {
            return ServiceResult.fail("新增话题组不能有topicGId");
        }
        TopicDO topicDO = new TopicDO(param.getProjectId(), param.getName(), param.getTopicGId(), param.getType(), TopicStatusEnum.NO_TRAIN.getIndex());
        if (TopicTypeEnum.TOPIC.getIndex() == param.getType()) {
            if (StringUtils.isBlank(param.getTopicGId())) {
                // 话题新增，查询默认话题组
                TopicDO defaultTopicDOGroup = topicDao.getDefaultTopicGroup(param.getProjectId());
                if (ObjectUtils.isEmpty(defaultTopicDOGroup)) {
                    defaultTopicDOGroup = topicDao.createDefaultTopicGroup(param.getProjectId());
                }
                topicDO.setTopicGID(defaultTopicDOGroup.getId());
            }
            if (!ObjectId.isValid(topicDO.getTopicGID())) {
                return ServiceResult.fail("话题组id格式错误");
            }
        }
        topicDO.setKeyDict(Collections.emptyList());
        TopicDO result = topicDao.saveTopic(topicDO);
        return ServiceResult.success(result.getId());
    }


    @Override
    public ServiceResult<String> updateTopic(UpdateTopicParam param) {
        String id = param.getId();
        List<String> keywords = param.getKeywords();
        String name = param.getName();

        TopicDO topicDO = topicDao.getById(id);
        if (ObjectUtils.isEmpty(topicDO)) {
            return ServiceResult.fail("话题id不存在");
        }
        if (DEFAULT_TOPIC_GROUP_NAME.equals(topicDO.getName()) && EMPTY.equals(topicDO.getTopicGID())) {
            return ServiceResult.fail("默认话题组不可以修改");
        }
        if (!param.isUpdateKeywordFlag()) {
            // 修改名称
            if (StringUtils.isBlank(name)) {
                return ServiceResult.fail("name不能为空");
            }
            if (this.checkNameRepeat(topicDO.getProjectId(), name)) {
                return ServiceResult.fail("该名称已在话题或者话题组中存在");
            }

            boolean updateResult = topicDao.updateNameOrKeywords(id, name, keywords);
            if (!updateResult) {
                return ServiceResult.fail("修改话题失败");
            }
        } else if (param.isUpdateKeywordFlag()) {
            // 修改关键词
            // 话题组判断
            if (topicDO.getType() == TopicTypeEnum.GROUP.getIndex()) {
                return ServiceResult.fail("话题组不可以添加关键词");
            }
            boolean updateResult = topicDao.updateKeyword(id, keywords);
            if (!updateResult) {
                return ServiceResult.fail("修改话题失败");
            }
        }
        return ServiceResult.success(id);
    }

    @Override
    public ServiceResult<String> deleteTopic(String topicId) {
        TopicDO topicDO = topicDao.getById(topicId);
        if (ObjectUtils.isEmpty(topicDO)) {
            return ServiceResult.fail("话题id不存在");
        }
        // 话题组删除判断，初始化话题组不能删除；话题组删除，组内的话题需要转移到默认话题组下
        if (TopicTypeEnum.GROUP.getIndex() == topicDO.getType()) {
            if (topicDO.getName().equals(DEFAULT_TOPIC_GROUP_NAME) &&
                    EMPTY.equals(topicDO.getTopicGID())) {
                return ServiceResult.fail("项目初始话题组不能删除");
            }
            boolean updateResult = topicDao.moveTopicToDefaultGroup(topicId, topicDO.getProjectId());
            if (!updateResult) {
                return ServiceResult.fail("话题删除失败");
            }
        }
        boolean deleteResult = topicDao.deleteById(topicId);
        if (!deleteResult) {
            return ServiceResult.fail("话题删除失败");
        }
        if (TopicTypeEnum.TOPIC.getIndex() == topicDO.getType()) {
            // 查询删除话题后剩余话题的关键词
            Set<String> topicKeyword = topicDao.listTopicKeyword(topicDO.getProjectId());
            List<String> keyDict = topicDO.getKeyDict();
            HashSet<String> removeHiddenWords = new HashSet<>(DEFAULT_ARRAY_SIZE);
            // 删除话题后，被删除话题的关键词如果在屏蔽关键词中，并且其它话题没有该关键词时，删除该屏蔽关键词
            if (CollUtil.isNotEmpty(keyDict)) {
                for (int i = 0; i < keyDict.size(); i++) {
                    String s = keyDict.get(i);
                    if (!topicKeyword.contains(s)) {
                        // 如果剩余话题中没有被删除的关键词
                        removeHiddenWords.add(s);
                    }
                }
            }
            HiddenKeywordDO hiddenKeywordDO = hiddenKeywordDao.findHiddenKeywords(topicDO.getProjectId());
            if (ObjectUtil.isEmpty(hiddenKeywordDO) || CollUtil.isEmpty(removeHiddenWords)) {
                return ServiceResult.success(topicId);
            }
            List<String> hiddenKeywords = hiddenKeywordDO.getKeywordList();
            int size = hiddenKeywords.size();
            // 去除被删除的屏蔽字
            CollUtil.removeAny(hiddenKeywords, removeHiddenWords.toArray(new String[removeHiddenWords.size()]));
            if (hiddenKeywords.size() != size) {
                boolean updateResult = hiddenKeywordDao.updateKeywords(topicDO.getProjectId(), CollUtil.list(false, hiddenKeywords));
                if (!updateResult) {
                    log.error("话题删除-去除被屏蔽关键词失败，projectId：{},topicId:{},需删除的被屏蔽关键词list：[{}]", topicDO.getProjectId(), topicId, hiddenKeywords);
                }
            }
        }
        return ServiceResult.success(topicId);
    }

    @Override
    public ServiceResult<List<TopicDataDTO>> exportTopicData(String projectId) {
        // 查看所有的话题
        List<TopicDO> groupList = topicDao.listTopicByType(projectId, TopicTypeEnum.GROUP.getIndex());
        Map<String, String> groupMap = groupList.stream().collect(Collectors.toMap(TopicDO::getId, TopicDO::getName));
        List<TopicDO> topicDOList = topicDao.listTopicByType(projectId, TopicTypeEnum.TOPIC.getIndex());
        List<TopicDataDTO> topicDataDTOS = new ArrayList<>(DEFAULT_ARRAY_SIZE);
        for (TopicDO topicDO : topicDOList) {
            if (CollUtil.isEmpty(topicDO.getKeyDict())) {
                continue;
            }
            for (String keyword : topicDO.getKeyDict()) {
                TopicDataDTO topicDataDTO = new TopicDataDTO(groupMap.get(topicDO.getTopicGID()), topicDO.getName(), keyword);
                topicDataDTOS.add(topicDataDTO);
            }
        }
        return ServiceResult.success(topicDataDTOS);
    }

    @Override
    public ServiceResult<Object> importTopicData(ImportTopicParam param) {
        List<TopicDataDTO> topicDatas = param.getTopicDatas();
        String projectId = param.getProjectId();
        Map<String, String> checkMap = new HashMap<>(DEFAULT_MAP_SIZE);
        Map<String, List<String>> groupMap = new HashMap<>(DEFAULT_MAP_SIZE);
        Map<String, List<String>> topicMap = new HashMap<>(DEFAULT_MAP_SIZE);

        // 上传数据校验
        for (TopicDataDTO topicData : topicDatas) {
            String keyword = topicData.getKeyword();
            String topicName = topicData.getTopicName();

            // 关键字不为空，则该行话题名也不可以为空
            if (StringUtils.isNotBlank(keyword) && StringUtils.isBlank(topicName)) {
                return ServiceResult.fail("关键字必须要属于一个话题");
            }
            // 如果话题名为空则该行数据跳过，也可以返回错误数据
            if (StringUtils.isBlank(topicName)) {
                continue;
            }
            // 话题组名为空，组名改为未分组
            String groupName = StringUtils.isBlank(topicData.getTopicGroupName()) ? DEFAULT_TOPIC_GROUP_NAME : topicData.getTopicGroupName();
            if (StringUtils.equals(groupName, topicName)) {
                return ServiceResult.fail("话题名的行内容和话题组的行内容不能重复");
            }
            if (StringUtils.length(keyword) > 50) {
                return ServiceResult.fail("关键字长度不能超过50");
            }
            if (StringUtils.length(topicName) > 20) {
                return ServiceResult.fail("话题名称长度不能超过20");
            }
            if (StringUtils.length(groupName) > 20) {
                return ServiceResult.fail("话题组名称长度不能超过20");
            }
            if (checkMap.containsKey(topicName) && !StringUtils.equals(checkMap.get(topicName), groupName)) {
                return ServiceResult.fail("一个话题只能属于一个话题组");
            }
            checkMap.put(topicName, groupName);
            assembleMap(groupName, topicName, groupMap);
            assembleMap(topicName, keyword, topicMap);
        }
        Set<String> groupNameSet = groupMap.keySet();
        Set<String> topicNameSet = topicMap.keySet();

        // 校验话题名和话题组名不能重复
        if (CollUtil.containsAny(groupNameSet, topicNameSet)) {
            return ServiceResult.fail("话题名的行内容和话题组的行内容不能重复");
        }
        // 校验库中已有数据
        List<TopicGroupInfoDO> topicGroupInfoDOS = topicDao.aggregateTopic(projectId);
        // 库中的话题名，key-话题名，value-话题id
        Map<String, String> dbTopicName = new HashMap<>(DEFAULT_MAP_SIZE);
        // 库中的话题组名，key-话题组名，value-话题组id
        Map<String, String> dbGroupName = new HashMap<>(DEFAULT_MAP_SIZE);
        for (TopicGroupInfoDO topicGroupInfoDO : topicGroupInfoDOS) {
            String groupName = topicGroupInfoDO.getName();
            String groupId = topicGroupInfoDO.getId();
            // 话题名与库中话题组名不能重复
            if (topicNameSet.contains(groupName)) {
                return ServiceResult.fail("话题名与已有的话题组名称重复");
            }
            List<TopicDO> topicDOList = topicGroupInfoDO.getTopicDOList();
            dbGroupName.put(groupName, groupId);
            for (TopicDO topicDO : topicDOList) {
                String name = topicDO.getName();
                // 话题组与库中话题名不能重复
                if (groupNameSet.contains(name)) {
                    return ServiceResult.fail("话题组名与已有的话题名称重复");
                }
                // 话题名在库中已存在，并且文件话题组名与库中话题组名不一致
                if (topicNameSet.contains(name) && !StringUtils.equals(checkMap.get(name), groupName)) {
                    return ServiceResult.fail("话题名已经属于一个存在的话题组");
                }
                dbTopicName.put(name, topicDO.getId());
            }
        }
        // 校验结束，修改表数据
        for (Map.Entry<String, List<String>> groupEntry : groupMap.entrySet()) {
            String groupName = groupEntry.getKey();
            String dbGroupId = dbGroupName.get(groupName);
            if (!dbGroupName.containsKey(groupName)) {
                // 话题组不存在
                dbGroupId = topicDao.insertGroup(projectId, groupName).getId();
                dbGroupName.put(groupName, dbGroupId);
            }
            for (String topicName : groupEntry.getValue()) {
                if (dbTopicName.containsKey(topicName)) {
                    // 话题已存在，以set的方式添加关键词
                    topicDao.appendKeywords(dbTopicName.get(topicName), topicName, topicMap.get(topicName));
                } else {
                    // 话题不存在，直接新增话题
                    TopicDO topicDO = topicDao.insertTopic(projectId, topicName, dbGroupId, topicMap.get(topicName));
                    dbTopicName.put(topicName, topicDO.getId());
                }
            }
        }
        return ServiceResult.success();
    }

    @Override
    public ServiceResult<String> moveTopic(MoveTopicParam param) {
        TopicDO topicDO = topicDao.getById(param.getId());
        if (ObjectUtils.isEmpty(topicDO)) {
            return ServiceResult.fail("话题id不存在");
        }
        String topicGroupId = param.getTopicGroupId();
        if (StringUtils.isNotBlank(topicGroupId) && !ObjectId.isValid(topicGroupId)) {
            return ServiceResult.fail("话题组id非法");
        }
        if (StringUtils.isBlank(topicGroupId)) {
            // 移动到新建话题组
            if (StringUtils.isBlank(param.getProjectId())) {
                return ServiceResult.fail("文本分析项目id不能为空");
            }
            if (this.checkNameRepeat(param.getProjectId(), param.getGroupName())) {
                return ServiceResult.fail("该名称已在话题或者话题组中存在");
            }
            TopicDO topicDOGroup = new TopicDO(param.getProjectId(), param.getGroupName(), EMPTY,
                    TopicTypeEnum.GROUP.getIndex(), TopicStatusEnum.NO_TRAIN.getIndex());

            topicGroupId = topicDao.saveTopic(topicDOGroup).getId();
        }
        // 修改被移动话题的话题组id
        boolean updateResult = topicDao.updateGroupIdById(param.getId(), topicGroupId);
        if (!updateResult) {
            return ServiceResult.fail("移动话题失败");
        }
        return ServiceResult.success(topicGroupId);
    }


    @Override
    public void initTopic(String projectId) {
        TopicDO groupTopicDO = new TopicDO();
        groupTopicDO = topicDao.insertGroup(projectId, "未分组");

        List<String> keyDict = new ArrayList<>();
        keyDict.add("好");
        topicDao.insertTopic(projectId, "质量", groupTopicDO.getId(), keyDict);
        List<String> topic = new ArrayList<>();
        topic.add("菜品");
        topic.add("服务");
        topic.add("环境");
        topic.add("其他");
        for (String topicCgr : topic) {
            TopicDO initTopicDO = topicDao.insertGroup(projectId, topicCgr);
            List<String> dicts = FREE_TOPIC_DICT.get(topicCgr);
            for (String dict : dicts) {
                List<String> keywords = FREE_KEYWORD_DICT.get(dict);
                topicDao.insertTopic(projectId, dict, initTopicDO.getId(), keywords);
            }
        }
    }


    /**
     * 检查话题名称是否重复
     *
     * @param projectId 文本分析项目id
     * @param name      话题名称
     * @return
     * @author liheng
     */
    private boolean checkNameRepeat(String projectId, String name) {
        if (!ObjectId.isValid(projectId) || StringUtils.isBlank(name)) {
            return false;
        }
        long count = topicDao.countByName(projectId, name);
        return count > 0;
    }

    private void assembleMap(String key, String value, Map<String, List<String>> map) {
        if (map.containsKey(key)) {
            List<String> strings = map.get(key);
            strings.add(value);
        } else {
            List<String> strings = new ArrayList<>(8);
            if (StringUtils.isNotBlank(value)) {
                strings.add(value);
            }
            map.put(key, strings);
        }
    }
}
